package org.example.StudentManagementSystem.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

import org.example.StudentManagementSystem.entity.User;
import org.example.StudentManagementSystem.common.Result;
import org.example.StudentManagementSystem.dto.response.UserDTO;
import org.example.StudentManagementSystem.dto.response.UserLoginDTO;
import org.example.StudentManagementSystem.dto.request.UserPasswordDTO;
import org.example.StudentManagementSystem.service.UserService;
import org.example.StudentManagementSystem.utils.TokenUtils;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@CrossOrigin(origins = "*")
@Tag(name = "用户管理", description = "用户注册、登录、信息管理等接口")
public class UserController {
    @Autowired
    private UserService userService;

    @Value("${server.port}")
    private String port;

    @Value("${file.upload-dir}")
    private String uploadDir;

    /**
     * 用户注册
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "新用户注册接口")
    @ApiResponse(responseCode = "200", description = "注册成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "用户名或密码不能为空")
    @ApiResponse(responseCode = "409", description = "用户名已存在")
    public Result register(@RequestBody User user) {
        if (user.getUsername() == null || user.getPassword() == null) {
            return Result.error("用户名或密码不能为空");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        if (userService.getOne(queryWrapper) != null) {
            return Result.error("用户名已存在");
        }
        String hashedPassword = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt());
        user.setPassword(hashedPassword);
        return userService.save(user) ? Result.success(user, "注册成功") : Result.error("注册失败");
    }

    /**
     * 用户登录
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录接口")
    @ApiResponse(responseCode = "200", description = "登录成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "用户名或密码不能为空")
    @ApiResponse(responseCode = "401", description = "用户名或密码错误")
    public Result login(@RequestBody User user) {
        if (user.getUsername() == null || user.getPassword() == null) {
            return Result.error("用户名或密码不能为空");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        User loginUser = userService.getOne(queryWrapper);
        if (loginUser == null) {
            return Result.error("用户名或密码错误");
        }
        if (BCrypt.checkpw(user.getPassword(), loginUser.getPassword())) {
            String token = TokenUtils.genToken(loginUser.getId().toString(), loginUser.getPassword());
            UserLoginDTO userLoginDTO = new UserLoginDTO();
            BeanUtils.copyProperties(loginUser, userLoginDTO);
            if (loginUser.getAvatar() != null) {
                userLoginDTO.setAvatar("http://localhost:" + port + "/file/avatar/" + userLoginDTO.getAvatar());
            }
            userLoginDTO.setToken(token);
            return Result.success(userLoginDTO, "登录成功");
        } else {
            return Result.error("用户名或密码错误");
        }
    }

    /**
     * 修改密码
     */
    @PostMapping("/password")
    @Operation(summary = "修改密码", description = "修改用户密码接口")
    @ApiResponse(responseCode = "200", description = "修改密码成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "旧密码错误")
    @ApiResponse(responseCode = "401", description = "用户未登录")
    public Result modifyPassword(@RequestBody UserPasswordDTO userPasswordDTO) {
        User user = TokenUtils.getCurrentUser();
        if (user == null) {
            return Result.error("请先登录");
        }
        if (BCrypt.checkpw(userPasswordDTO.getOldPassword(), user.getPassword())) {
            String hashedPassword = BCrypt.hashpw(userPasswordDTO.getNewPassword(), BCrypt.gensalt());
            user.setPassword(hashedPassword);
            return userService.updateById(user) ? Result.success("修改密码成功") : Result.error("修改密码失败");
        } else {
            return Result.error("旧密码错误");
        }
    }

    /**
     * 获取用户列表
     */
    @GetMapping("")
    @Operation(summary = "获取用户列表", description = "分页获取用户列表接口")
    @ApiResponse(responseCode = "200", description = "获取用户列表成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "404", description = "暂无数据")
    @Parameter(name = "page", description = "当前页码", required = true, example = "1")
    @Parameter(name = "size", description = "每页大小", required = true, example = "10")
    public Result getUserList(@RequestParam(defaultValue = "1") int page, @RequestParam(defaultValue = "10") int size) {
        Page<User> userPage = userService.page(Page.of(page, size));
        userPage.getRecords().forEach(user -> {
            user.setPassword(null);
            if (user.getAvatar() != null) {
                user.setAvatar("http://localhost:" + port + "/file/avatar/" + user.getAvatar());
            }
        });
        if (userPage.getTotal() == 0) {
            return Result.error("暂无数据");
        }
        return Result.success(userPage, "获取用户列表成功");
    }

    /**
     * 获取所有用户
     */
    @GetMapping("/all")
    @Operation(summary = "获取所有用户", description = "获取所有用户接口")
    @ApiResponse(responseCode = "200", description = "获取所有用户成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    public Result getAllUser() {
        List<User> userList = userService.list();
        userList.forEach(user -> {
            user.setPassword(null);
            if (user.getAvatar() != null) {
                user.setAvatar("http://localhost:" + port + "/file/avatar/" + user.getAvatar());
            }
        });
        return Result.success(userList, "获取所有用户成功");
    }

    /**
     * 获取用户信息
     */
    @GetMapping("/{id}")
    @Operation(summary = "获取用户信息", description = "根据用户ID获取用户信息接口")
    @ApiResponse(responseCode = "200", description = "获取用户成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "404", description = "用户不存在")
    @Parameter(name = "id", description = "用户ID", required = true, example = "1")
    public Result getUserById(@PathVariable int id) {
        User user = userService.getById(id);
        if (user == null) {
            return Result.error("用户不存在");
        }
        user.setPassword(null);

        if (user.getAvatar() != null) {
            user.setAvatar("http://localhost:" + port + "/file/avatar/" + user.getAvatar());
        }
        return Result.success(user, "获取用户成功");
    }

    /**
     * 修改用户信息
     */
    @PutMapping("/{id}")
    @Operation(summary = "修改用户信息", description = "根据用户ID修改用户信息接口")
    @ApiResponse(responseCode = "200", description = "修改用户成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "用户名不能为空")
    @ApiResponse(responseCode = "404", description = "用户不存在")
    @Parameter(name = "id", description = "用户ID", required = true, example = "1")
    public Result updateUser(@PathVariable int id, @RequestBody User user) {
        User oldUser = userService.getById(id);
        if (oldUser == null) {
            return Result.error("用户不存在");
        }
        if (user.getUsername() == null) {
            return Result.error("用户名不能为空");
        }
        oldUser.setUsername(user.getUsername());
        oldUser.setNickname(user.getNickname());
        oldUser.setGender(user.getGender());
        oldUser.setPhone(user.getPhone());
        oldUser.setEmail(user.getEmail());
        String avatar = user.getAvatar();
        if (avatar != null && !avatar.isEmpty() && !avatar.equals("null")) {
            String fileName = avatar.substring(avatar.lastIndexOf("/") + 1);
            File file = new File(uploadDir + "/" + fileName);
            if (file.exists()) {
                oldUser.setAvatar(fileName);
            } else {
                return Result.error("上传文件不存在");
            }
        }
        boolean flag = userService.updateById(oldUser);
        if (!flag) {
            return Result.error("修改用户失败");
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(oldUser, userDTO);
        if (oldUser.getAvatar() != null) {
            userDTO.setAvatar("http://localhost:" + port + "/file/avatar/" + userDTO.getAvatar());
        }
        return Result.success(userDTO, "修改用户成功");
    }

    /**
     * 删除用户
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除用户", description = "根据用户ID删除用户接口")
    @ApiResponse(responseCode = "200", description = "用户删除成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "403", description = "无法删除自己")
    @ApiResponse(responseCode = "404", description = "用户不存在")
    @Parameter(name = "id", description = "用户ID", required = true, example = "1")
    public Result deleteUser(@PathVariable int id) {
        if (Objects.requireNonNull(TokenUtils.getCurrentUser()).getId() == id) {
            return Result.error("无法删除自己");
        }
        User user = userService.getById(id);
        if (user == null) {
            return Result.error("用户不存在");
        }
        return userService.removeById(id) ? Result.success("用户删除成功") : Result.error("用户删除失败");
    }

    /**
     * 批量删除用户
     */
    @DeleteMapping("")
    @Operation(summary = "批量删除用户", description = "批量删除用户接口")
    @ApiResponse(responseCode = "200", description = "批量删除成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "请选择要删除的用户")
    @ApiResponse(responseCode = "404", description = "用户不存在")
    public Result deleteUsers(@RequestBody int[] ids) {
        if (ids.length == 0) {
            return Result.error("请选择要删除的用户");
        }
        for (int id : ids) {
            User user = userService.getById(id);
            if (user == null) {
                return Result.error("用户不存在");
            }
        }
        List<Integer> idList = Arrays.stream(ids).boxed().collect(Collectors.toList());
        return userService.removeByIds(idList) ? Result.success("批量删除成功") : Result.error("批量删除失败");
    }

    /**
     * 添加用户
     */
    @PostMapping("")
    @Operation(summary = "添加用户", description = "添加新用户接口")
    @ApiResponse(responseCode = "200", description = "添加成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "用户名或密码不能为空")
    @ApiResponse(responseCode = "409", description = "用户名已存在")
    public Result addUser(@RequestBody User user) {
        if (user.getUsername() == null || user.getPassword() == null) {
            return Result.error("用户名或密码不能为空");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        if (userService.getOne(queryWrapper) != null) {
            return Result.error("用户名已存在");
        }
        String hashedPassword = BCrypt.hashpw(user.getPassword(), BCrypt.gensalt());
        user.setPassword(hashedPassword);
        boolean flag = userService.save(user);
        if (!flag) {
            return Result.error("添加失败");
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(user, userDTO);
        if (userDTO.getAvatar() != null) {
            userDTO.setAvatar("http://localhost:" + port + "/file/avatar/" + userDTO.getAvatar());
        }
        return Result.success(userDTO, "添加成功");
    }

    /**
     * 上传头像
     */
    @PostMapping("/avatar/upload")
    @Operation(summary = "上传头像", description = "上传用户头像接口")
    @ApiResponse(responseCode = "200", description = "文件上传成功",
            content = @Content(schema = @Schema(implementation = Result.class)))
    @ApiResponse(responseCode = "400", description = "上传文件不能为空")
    @ApiResponse(responseCode = "401", description = "用户未登录")
    @ApiResponse(responseCode = "500", description = "文件上传失败")
    @Parameter(name = "file", description = "要上传的头像文件", required = true)
    public Result uploadAvatar(@RequestParam("file") MultipartFile file) {
        User user = TokenUtils.getCurrentUser();
        if (user == null) {
            return Result.error("401", "用户未登录");
        }
        if (file.isEmpty()) {
            return Result.error("400", "上传文件不能为空");
        }
        try {
            // 生成唯一的文件名
            String fileName = UUID.randomUUID() + "_" + file.getOriginalFilename();
            Path filePath = Paths.get(uploadDir, fileName).normalize();
            // 确保上传目录存在
            Files.createDirectories(filePath.getParent());
            // 保存文件
            file.transferTo(filePath.toFile());
            String avatarUrl = "http://127.0.0.1:" + port + "/file/avatar/" + fileName;
            // 更新用户头像路径
            return Result.success(avatarUrl, "文件上传成功");
        } catch (IOException e) {
            return Result.error("500", "文件上传失败: " + e.getMessage());
        }
    }
}
